/*
 * Copyright 2007 Brian Watkins
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package bw.os;

import java.io.*;
import java.net.*;
import javax.servlet.*;
import bw.net.*;
import bw.util.*;

public class HttpObjectReader extends PersistentObjectHandler implements PersistentObjectReader
{
    public static final String REMOTE_GET = "/get";

    private String _httpRoot = null;
    //private PersistentObjectWriter _localWriter = null;

    public HttpObjectReader ( ServletContext context )
    {
        super();

        _httpRoot = context.getInitParameter( "objectStore.httpReader.root" );

        Log.getInstance().write( "Using HttpObjectReader at: " + _httpRoot );

        /*if ( "true".equalsIgnoreCase( context.getInitParameter( "objectStore.http.backupLocally" ) ) )
        {
            Log.getInstance().write( "Using local disc cache for backups of http remote store data." );
            _localWriter = new FileObjectHandler( context );
            }*/
    }

    public HttpObjectReader ( String httpRoot )
    {
        super();
        
        _httpRoot = httpRoot;

        Log.getInstance().write( "Using HttpObjectReader at: " + _httpRoot );
    }

    public Object read ( String key ) throws Exception
    {
        return read( key, 0 );
    }

    public Object read ( String key, int attempts ) throws Exception
    {
        String filename = makeFilename( key );

        NetResource resource = new NetResource( _httpRoot + REMOTE_GET + "/" + filename );

        HttpURLConnection conn = resource.getURLConnection();
        
        Object obj = null;
        if ( conn != null )
        {
            obj = getObjectFromStream( conn.getInputStream() );
        }
        else
        {
            if ( resource.getError() == NetResource.NETWORK_DOWN )
            {
                //if the network goes down then we must block here and try
                //again after sleeping. If we return null and the object is actually
                //there then it will almost surely be overwritten by the caller. 
                attempts++;

                //only try three times
                if ( attempts > 3 )
                {
                    Log.getInstance().write( "HttpObjectReader: Network is down. Failing on attempt to get: " +
                                             makeFilename( key ) );
                    throw new ObjectStoreException( "Network down!" ); 
                }
                else
                {
                    Log.getInstance().write( "HttpObjectReader: Network appears to " +
                                             "be down while getting http object: " + 
                                             makeFilename( key ) + " (Attempt #" + attempts + ")" );
                    
                    try
                    {
                        Log.getInstance().write( "HttpObjectReader: Sleeping for 1 minute" );
                        Thread.sleep( 60 * 1000L );
                    }
                    catch ( InterruptedException ex )
                    {
                        //nothing
                    }
                
                    Log.getInstance().write( "HttpObjectReader: Warning! Recursively " +
                                             "requesting object: " + makeFilename( key ) );
                    obj = read( key, attempts );
                }
            }
            else if ( resource.getError() == NetResource.HTTP_NOT_OK )
            {
                if ( resource.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND )
                {
                    Log.getInstance().write( "HttpObjectReader: Object not found: " + 
                                             makeFilename( key ) );
                }
                else
                {
                    Log.getInstance().write( "HttpObjectReader: Http Error getting http " +
                                             "object (" + makeFilename( key ) + "): " + 
                                             resource.getResponseCode() );
                    throw new ObjectStoreException( "Http Error!" );
                }
            }
            else
            {
                Log.getInstance().write( "HttpObjectReader: Unknown error getting http object: " + 
                                         makeFilename( key ) );
                throw new ObjectStoreException( "Http Unknown Error!" );
            }
        }

        /*if ( _localWriter != null && obj != null )
        {
            _localWriter.write( key, obj );
            }*/

        return obj;
    }

    public void shutdown () throws Exception
    {
        //nothing
    }
}